package com.tiecode.string.encoder;

import com.qiplat.api.framework.common.setting.SettingProvider;
import com.qiplat.api.plugin.util.PluginEnvironment;
import com.qiplat.develop.util.firstparty.android.AssetUtils;
import com.qiplat.framework.Qiplat;
import com.tiecode.platform.compiler.api.file.FileManager;
import com.tiecode.platform.compiler.api.file.TiecodeTempFile;
import com.tiecode.platform.compiler.api.log.Messager;
import com.tiecode.platform.compiler.api.process.TaskEvent;
import com.tiecode.platform.compiler.api.process.Trees;
import com.tiecode.platform.compiler.source.tree.CompilationUnitTree;
import com.tiecode.platform.compiler.toolchain.completer.RoundEnter;
import com.tiecode.platform.compiler.toolchain.env.Context;
import com.tiecode.platform.compiler.toolchain.env.Options;
import com.tiecode.platform.compiler.toolchain.processor.AnnotationProvider;
import com.tiecode.platform.compiler.toolchain.tree.TCTree;
import com.tiecode.platform.compiler.toolchain.tree.code.TiecodeTrees;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import cn.tiecode.api.event.TiecodeCompilerEvent;

public final class MyCompilerEvent implements TiecodeCompilerEvent {
    private Context context;
    private SettingProvider settingProvider;

    @Override
    public void init(Context context) {
        this.context = context;
        this.settingProvider = Qiplat.getSettingProvider();
    }

    @Override
    public void onProvideAnnotation(AnnotationProvider annotationProvider) {

    }

    @Override
    public void onEventStarted(TaskEvent event) {
        if (Options.instance(context).outPath == null) {
            return;
        }
        switch (event.getKind()) {
            case PARSE:
                if (settingProvider.getBoolean(MySettingManager.KEY_ENCODE_ENABLED, true)) {
                    writeDecodeSource();
                }
                break;
            case ANALYZE:
                if (settingProvider.getBoolean(MySettingManager.KEY_ENCODE_ENABLED, true)) {
                    Messager messager = context.get(Messager.key);
                    messager.info("执行字符串加密...");
                    modifyStrings();
                }
                break;
        }
    }

    @Override
    public void onEventFinished(TaskEvent taskEvent) {

    }

    private void writeDecodeSource() {
        String filename = "decode-android.t";
        Options.Target target = Options.instance(context).target;
        if (target == Options.Target.LINUX) {
            filename = "decode-linux.t";
        } else if (target == Options.Target.WEBPAGE) {
            filename = "decode-js.t";
        }
        String content = null;
        try {
            content = AssetUtils.readAsset(PluginEnvironment.getContext(this), filename);
            FileManager manager = context.get(FileManager.key);
            manager.addSourceFile(new TiecodeTempFile(filename, content));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void modifyStrings() {
        boolean logEnabled = settingProvider.getBoolean(MySettingManager.KEY_ENCODE_LOG, true);
        Trees trees = TiecodeTrees.instance(context);
        List<? extends CompilationUnitTree> units = trees.getCompilationUnits();
        List<TCTree.TCCompilationUnit> newUnits = new ArrayList<>();
        for (CompilationUnitTree unit : units) {
            TCTree.TCCompilationUnit root = (TCTree.TCCompilationUnit) unit;
            if (!root.symbol.name.contentEquals(Options.instance(context).namespace)) {
                continue;
            }
            StringEncoder encoder = new StringEncoder(context, logEnabled);
            encoder.modify(root);
            newUnits.add(root);
        }
        RoundEnter enter = RoundEnter.instance(context);
        enter.complete(newUnits);
    }
}
